<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2022-9-28 10:55:00
// +----------------------------------------------------------------------
namespace buwang\util\console;


class CliRun
{
    /**
     * 执行命令
     * @param string $cwd 要执行命令的初始工作目录
     * @param string $command 要执行的命令
     * @return string|\think\Response
     */
    public static function execute(string $cwd, string $command) {
        if (!function_exists('proc_open') || !function_exists('proc_close')) {
            return 'Function proc_open or proc_close disabled';
        }

        // 设置执行时长
        set_time_limit(0);

        // 执行命令，并将输出保存到变量中
        $description = array(
            0 => array("pipe", "r"),  // 标准输入
            1 => array("pipe", "w"),  // 标准输出
            2 => array("pipe", "w")   // 标准错误
        );

        $process = proc_open($command, $description, $pipes, $cwd);

        // 检查进程是否成功创建
        if (!is_resource($process)) {
            return "Could not execute command: $command";
        }

        // 从管道中获取命令的输出
        $output = '';
        $errorOutput = '';

        // 分别读取标准输出和错误输出
        while (!feof($pipes[1])) {
            $output .= fgets($pipes[1]);
        }
        while (!feof($pipes[2])) {
            $errorOutput .= fgets($pipes[2]);
        }

        // 关闭管道
        fclose($pipes[0]);
        fclose($pipes[1]);
        fclose($pipes[2]);

        // 获取进程状态
        $status = proc_close($process);

        // 合并输出和错误
        $fullOutput = $output . $errorOutput;

        // 判断命令执行结果
        if ($status === 0) {
            // 即使状态码为0，也要检查是否有PHP错误或异常
            if (preg_match('/(Fatal error|Exception|Error:|Warning:|Notice:|Command failed)/i', $fullOutput)) {
                return $fullOutput; // 返回错误信息
            }
            return true; // 真正的成功
        } else {
            return $fullOutput; // 返回错误信息
        }
    }
}